package vip.xiaonuo.sys.modular.courseselection.service.impl;

import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.core.context.login.LoginContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.pojo.login.SysLoginUser;
import vip.xiaonuo.core.util.CommonUtil;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.sys.modular.coursehomework.result.HomeworkResult;
import vip.xiaonuo.sys.modular.coursepublish.entity.CoursePublish;
import vip.xiaonuo.sys.modular.coursepublish.mapper.CoursePublishMapper;
import vip.xiaonuo.sys.modular.coursepublish.param.CoursePublishParam;
import vip.xiaonuo.sys.modular.coursepublish.result.CoursePublishResult;
import vip.xiaonuo.sys.modular.coursepublishfrequency.entity.CoursePublishFrequency;
import vip.xiaonuo.sys.modular.coursepublishfrequency.mapper.CoursePublishFrequencyMapper;
import vip.xiaonuo.sys.modular.courseschedule.entity.CourseSchedule;
import vip.xiaonuo.sys.modular.courseschedule.mapper.CourseScheduleMapper;
import vip.xiaonuo.sys.modular.courseschedule.vo.CoursePublishFrequencyItemVo;
import vip.xiaonuo.sys.modular.courseschedule.vo.CourseScheduleVo;
import vip.xiaonuo.sys.modular.courseschedulefrequency.entity.CourseScheduleFrequency;
import vip.xiaonuo.sys.modular.courseschedulefrequency.mapper.CourseScheduleFrequencyMapper;
import vip.xiaonuo.sys.modular.courseselection.dto.CourseSelectionQryDto;
import vip.xiaonuo.sys.modular.courseselection.entity.CourseSelection;
import vip.xiaonuo.sys.modular.courseselection.enums.CourseSelectionExceptionEnum;
import vip.xiaonuo.sys.modular.courseselection.mapper.CourseSelectionMapper;
import vip.xiaonuo.sys.modular.courseselection.service.CourseSelectionService;
import vip.xiaonuo.sys.modular.courseselection.vo.CourseSelectionBaesVo;
import vip.xiaonuo.sys.modular.courseselection.vo.CourseSelectionDetailVo;
import vip.xiaonuo.sys.modular.courseselection.vo.CourseSelectionResultVo;
import vip.xiaonuo.sys.modular.courseselection.vo.CourseSelectionStuVo;
import vip.xiaonuo.sys.modular.sysschoolterm.entity.SysSchoolTerm;
import vip.xiaonuo.sys.modular.sysschoolterm.mapper.SysSchoolTermMapper;
import vip.xiaonuo.sys.modular.sysschoolyear.entity.SysSchoolYear;
import vip.xiaonuo.sys.modular.sysschoolyear.mapper.SysSchoolYearMapper;
import vip.xiaonuo.sys.modular.tstudenttag.mapper.TStudentTagMapper;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.mapper.SysUserMapper;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author 墨塵
 * @since 2022/7/20
 */
@Service
@Transactional
public class CourseSelectionServiceImpl extends ServiceImpl<CourseSelectionMapper, CourseSelection> implements CourseSelectionService {

    @Resource
    private TStudentTagMapper studentTagMapper;

    @Resource
    private SysUserMapper userMapper;

    @Resource
    private SysSchoolYearMapper schoolYearMapper;

    @Resource
    private SysSchoolTermMapper schoolTermMapper;

    @Resource
    private CoursePublishMapper coursePublishMapper;

    @Resource
    private CoursePublishFrequencyMapper coursePublishFrequencyMapper;

    @Resource
    private CourseScheduleMapper courseScheduleMapper;

    @Resource
    private CourseScheduleFrequencyMapper courseScheduleFrequencyMapper;

    @Resource
    private CourseSelectionMapper courseSelectionMapper;

    @Override
    public CourseSelectionBaesVo getBaseInfo(CourseSelectionQryDto dto) {
        CourseSelectionBaesVo result = new CourseSelectionBaesVo();
        //当前登录用户
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        //学院ID
        Long collegeId = dto.getCollegeId();
        if (collegeId == null) {
            collegeId = sysLoginUser.getCollId();
        }
        //学生标签描述
        Long userId = dto.getUserId();
        if (userId == null) {
            userId = sysLoginUser.getId();
        }
        String stuTagDesc = studentTagMapper.getTagDescByUserId(userId);
        if (StringUtils.isNotBlank(stuTagDesc)) {
            stuTagDesc = stuTagDesc.replaceAll(",", "、");
        }
        result.setStuTagDesc(stuTagDesc);
        //学生信息
        SysUser userInfo = userMapper.selectById(userId);
        result.setUserInfo(userInfo);
        //学年
        SysSchoolYear schoolYear = schoolYearMapper.getInfoById(dto.getSchoolYearId());
        result.setSchoolYear(schoolYear);
        //学期
        SysSchoolTerm schoolTerm = schoolTermMapper.getInfoById(dto.getSchoolTermId());
        result.setSchoolTerm(schoolTerm);

        List<CoursePublishResult> coursePublishList = new ArrayList<>();
        if(dto.getCoursePublishId()!=null){
            //有开课ID直接拿
            coursePublishList.add(coursePublishMapper.getInfoById(dto.getCoursePublishId()));
        }else{
            if (schoolYear != null && schoolTerm != null) {
                //课程信息
                CoursePublishParam coursePublishParam = new CoursePublishParam();
                coursePublishParam.setCollegeId(collegeId);
                coursePublishParam.setSchoolYearId(schoolYear.getId());
                coursePublishParam.setTermId(schoolTerm.getId());
                coursePublishParam.setStuId(userId);
                coursePublishParam.setPublishState(dto.getPublishState());
                coursePublishList = coursePublishMapper.getEffListByParam(coursePublishParam);
            }
        }
        result.setCoursePublishList(coursePublishList);
        return result;
    }

    @Override
    public JSONObject getCryInfo(CourseSelectionQryDto dto) {
        JSONObject result = new JSONObject();
        //当前登录用户
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        Long userId = dto.getUserId();
        if (userId == null || sysLoginUser.getAdminType() == 4) {
            //学生强制拿自己的
            userId = sysLoginUser.getId();
            dto.setUserId(userId);
        }
        //限制的项目id
        List<Long> projectIds = courseSelectionMapper.getProjectListForUser(dto);
        //限制的排课id
        List<Long> courseScheduleIds = new ArrayList<>();
        //限制的排课轮次
        List<Integer> frequencyIndexs = new ArrayList<>();
        //获取当前课程的选课记录
        List<CourseSelection> selectionList = courseSelectionMapper.getAllList(dto);
        //添加限制的轮次+实验项目
        for (CourseSelection selectionItem : selectionList) {
            if (selectionItem.getStudentId().equals(userId)) {
                courseScheduleIds.add(selectionItem.getCourseScheduleId());
                frequencyIndexs.add(selectionItem.getFrequencyIndex());
            }
        }
        //获取开课信息
        List<CoursePublishFrequency> coursePublishFrequencyList = coursePublishFrequencyMapper.getListByPublishId(dto.getCoursePublishId());
        result.put("coursePublishFrequencyList", coursePublishFrequencyList);

        //获取排课信息（按照上课日拆成多条数据）
        List<CourseScheduleVo> courseScheduleVoList = new ArrayList<>();
        List<CourseScheduleVo> scheduleVoList = courseScheduleMapper.getListByPublishId(dto.getCoursePublishId());

        for (CourseScheduleVo scheduleVo : scheduleVoList) {
            int index = 0;

            //获取排课轮次
            List<CourseScheduleFrequency> frequencyList = courseScheduleFrequencyMapper.getListByCourseScheduleId(scheduleVo.getId());
            //获取排课日期(去重)
            List<Integer> days = new ArrayList<>();
            for (CourseScheduleFrequency frequency : frequencyList) {
                //拆分具体上课日期
                List<String> dayList = new ArrayList<>(Arrays.asList(frequency.getDayOfWeek().split(",")));
                for (String day : dayList) {
                    if (!days.contains(Integer.valueOf(day))) {
                        days.add(Integer.valueOf(day));
                    }
                }
            }
            //按正序排序   天→排课轮次→根据天按照轮次裂变多条数据
            Collections.sort(days);
            for (Integer day : days) {
                CourseScheduleVo entity = new CourseScheduleVo();
                BeanUtil.copyProperties(scheduleVo, entity);
                entity.setFrequencyDay(day);
                List<CoursePublishFrequencyItemVo> frequencyItemVoList = new ArrayList<>();
                //抓取排课轮次数据
                for (CourseScheduleFrequency frequency : frequencyList) {
                    if (frequency.getDayOfWeek().contains(day.toString())) {
                        //选课数量
                        int courseSelectionNum = 0;
                        CoursePublishFrequencyItemVo frequencyItemVo = new CoursePublishFrequencyItemVo();
                        frequencyItemVo.setFrequencyIndex(frequency.getFrequencyIndex());
                        frequencyItemVo.setCourseScheduleFrequencyId(frequency.getId());
                        frequencyItemVo.setCourseScheduleId(frequency.getCourseScheduleId());
                        frequencyItemVo.setCoursePublishId(dto.getCoursePublishId());
                        //根据选课记录处理可选项等
                        if (!CollectionUtil.isEmpty(selectionList)) {
                            for (CourseSelection selection : selectionList) {
//                                if (selection.getCourseScheduleFrequencyId().equals(frequency.getId()) && selection.getCourseScheduleId().equals(frequency.getCourseScheduleId()) && selection.getFrequencyIndex().equals(frequency.getFrequencyIndex()) && selection.getFrequencyDay().equals(day)) {
//                                    courseSelectionNum += 1;
//                                    if (selection.getStudentId().equals(userId)) {
//                                        frequencyItemVo.setCourseSelectionId(selection.getId());
//                                        frequencyItemVo.setOptType(selection.getOptType());
//                                    }
//                                }
                                //更改排课最大人数 表b_course_schedule_frequency 会重置 所以根据轮次+星期进行匹配
                                if (selection.getCourseScheduleId().equals(frequency.getCourseScheduleId()) && selection.getCourseScheduleId().equals(frequency.getCourseScheduleId()) && selection.getFrequencyIndex().equals(frequency.getFrequencyIndex()) && selection.getFrequencyDay().equals(day)) {
                                    courseSelectionNum += 1;
                                    if (selection.getStudentId().equals(userId)) {
                                        frequencyItemVo.setCourseSelectionId(selection.getId());
                                        frequencyItemVo.setOptType(selection.getOptType());
                                    }
                                }
                                //满员
                                if (courseSelectionNum == scheduleVo.getMaxStudents()) {
                                    frequencyItemVo.setFullFlag(true);
                                }
                                //排课or轮次 只能选1
                                if (courseScheduleIds.contains(frequency.getCourseScheduleId()) || frequencyIndexs.contains(frequency.getFrequencyIndex())) {
                                    frequencyItemVo.setOptFlag(false);
                                }
                                //同一项目只能选1
                                if(projectIds.contains(scheduleVo.getProjectId())){
                                    frequencyItemVo.setOptFlag(false);
                                }
                            }
                        }
                        frequencyItemVo.setCourseSelectionNum(courseSelectionNum);
                        frequencyItemVoList.add(frequencyItemVo);
                    }
                }
                if (!CollectionUtil.isEmpty(frequencyItemVoList)) {
                    entity.setCoursePublishFrequencyItemVoList(frequencyItemVoList);
                }
                if (index == 0) {
                    entity.setRowSpan(days.size());
                } else {
                    entity.setRowSpan(0);
                }
                courseScheduleVoList.add(entity);
                index++;
            }
            //转换排课列表为json
            JSONArray array = new JSONArray();
            for (CourseScheduleVo item : courseScheduleVoList) {
                JSONObject cs = JSONObject.parseObject(JSON.toJSONString(item));
                cs.remove("coursePublishFrequencyItemVoList");
                for (CoursePublishFrequencyItemVo cpfItem : item.getCoursePublishFrequencyItemVoList()) {
                    cs.put("frequencyIndex-" + cpfItem.getFrequencyIndex(), cpfItem);
                }
                array.add(cs);
            }
            result.put("courseScheduleVoList", array);
        }

        return result;
    }

    @Override
    public int toSelection(CourseSelection entity) {
        //当前登录用户
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        Long userId = entity.getStudentId();
        if (userId == null || sysLoginUser.getAdminType() == 4) {
            //学生强制拿自己的
            userId = sysLoginUser.getId();
            entity.setStudentId(userId);
            entity.setOptType(0);
            //校验是否在开课时间范围内
            CoursePublish coursePublishInfo = coursePublishMapper.getInfoByIdInTime(entity.getCoursePublishId());
            if(coursePublishInfo==null){
                throw new ServiceException(CourseSelectionExceptionEnum.CP_OVERTIME);
            }
        } else {
            entity.setOptType(1);
        }
        //学生校验选课
        if (sysLoginUser.getAdminType() == 4) {
            //学生校验选课是否合格(规则 同一轮次or排课唯一)
            List<CourseSelection> selectionList = courseSelectionMapper.getListForCheck(entity);
            if (!CollectionUtil.isEmpty(selectionList)) {
                throw new ServiceException(CourseSelectionExceptionEnum.REPEAT_DATA);
            }
        }
        //获取排课最大人数
        CourseSchedule courseSchedule = courseScheduleMapper.selectById(entity.getCourseScheduleId());
        //获取当前实验项目的报名人数
        int selectionNum = courseSelectionMapper.countRecrd(entity);
        if (selectionNum + 1 > courseSchedule.getMaxStudents()) {
            throw new ServiceException(CourseSelectionExceptionEnum.EXCEED_NUM);
        }
        //插入数据
        return courseSelectionMapper.insert(entity);
    }

    @Override
    public int cancelSelection(CourseSelection entity) {
        //当前登录用户
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        Long userId = entity.getStudentId();
        if (userId == null || sysLoginUser.getAdminType() == 4) {
            //学生强制拿自己的
            userId = sysLoginUser.getId();
            //获取选课信息
            CourseSelection csInfo =courseSelectionMapper.selectById(entity.getId());
            if(csInfo==null){
                throw new ServiceException(CourseSelectionExceptionEnum.NOT_CS_INFO);
            }
            //校验是否在开课时间范围内
            CoursePublish coursePublishInfo = coursePublishMapper.getInfoByIdInTime(csInfo.getCoursePublishId());
            if(coursePublishInfo==null){
                throw new ServiceException(CourseSelectionExceptionEnum.CP_OVERTIME);
            }
        }
        UpdateWrapper<CourseSelection> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("student_id", userId);
        updateWrapper.eq("id", entity.getId());
        CourseSelection selection = new CourseSelection();
        selection.setStatus(2);
        return courseSelectionMapper.update(selection, updateWrapper);

    }

    @Override
    public int emptySelection(CourseSelectionQryDto dto) {
        //当前登录用户
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        Long userId = dto.getUserId();
        if (userId == null || sysLoginUser.getAdminType() == 4) {
            //学生强制拿自己的
            userId = sysLoginUser.getId();
            //校验是否在开课时间范围内
            CoursePublish coursePublishInfo = coursePublishMapper.getInfoByIdInTime(dto.getCoursePublishId());
            if(coursePublishInfo==null){
                throw new ServiceException(CourseSelectionExceptionEnum.CP_OVERTIME);
            }
        }
        UpdateWrapper<CourseSelection> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("student_id", userId);
        updateWrapper.eq("course_publish_id", dto.getCoursePublishId());
        CourseSelection selection = new CourseSelection();
        selection.setStatus(2);
        return courseSelectionMapper.update(selection, updateWrapper);
    }

    @Override
    public List<CourseSelectionDetailVo> getCsDetailList(CourseSelectionQryDto dto) {
        return courseScheduleMapper.getCsDetailList(dto);
    }

    @Override
    public void exportCsDetailList(CourseSelectionQryDto dto) {
        //开课信息
        CoursePublishResult coursePublishResult = coursePublishMapper.getInfoById(dto.getCoursePublishId());
        //选课列表'
        List<CourseSelectionDetailVo> list = courseScheduleMapper.getCsDetailList(dto);
        for(CourseSelectionDetailVo item : list){
            if(item.getCheckResult()==0){
                item.setCheckResultStr("不合格");
            }else{
                item.setCheckResultStr("合格");
            }
        }
        //文件名称
        String fileName = "课表-" + coursePublishResult.getCollegeName() + "[" + coursePublishResult.getSchoolYearName() + "]" + "[" + coursePublishResult.getTermName() + "]" + "[" + coursePublishResult.getCourseName() + "]";
        PoiUtil.exportExcelWithStream(fileName+"学生选课详情.xls", CourseSelectionDetailVo.class, list);
    }

    @Override
    public void exportSelection(CourseSelectionQryDto dto) {
        //获取开课信息
        CoursePublishResult coursePublishResult = coursePublishMapper.getInfoById(dto.getCoursePublishId());
        //获取开课轮次
        List<CoursePublishFrequency> coursePublishFrequencyList = coursePublishFrequencyMapper.getListByPublishId(dto.getCoursePublishId());
        //获取排课信息
        List<CourseScheduleVo> scheduleVoList = courseScheduleMapper.getListByPublishId(dto.getCoursePublishId());
        //获取当前课程的选课记录
        List<CourseSelectionResultVo> selectionList = courseSelectionMapper.getResultList(dto);

        //表头
        List<ExcelExportEntity> beanList = new ArrayList<ExcelExportEntity>();
        beanList.add(new ExcelExportEntity("实验项目", "column_1"));

        //教师行
        Map<String, Object> rows_t = new HashMap<>();
        rows_t.put("column_1", "教师");
        //教室行
        Map<String, Object> rows_c = new HashMap<>();
        rows_c.put("column_1", "实验室");
        //日期行
        Map<String, Object> rows_d = new HashMap<>();
        rows_d.put("column_1", "开课日期");
        //绘制表头
        for (int i = 0; i < scheduleVoList.size(); i++) {
            String projectName = "(" + (i + 1) + ") " + scheduleVoList.get(i).getProjectName();
            beanList.add(new ExcelExportEntity(projectName, "project_" + (i + 1)));

            rows_t.put("project_" + (i + 1), scheduleVoList.get(i).getTeacherName());
            rows_c.put("project_" + (i + 1), scheduleVoList.get(i).getClassroomName());

            //获取排课轮次
            List<CourseScheduleFrequency> frequencyList = courseScheduleFrequencyMapper.getListByCourseScheduleId(scheduleVoList.get(i).getId());
            //获取排课日期(去重)
            List<Integer> days = new ArrayList<>();
            for (CourseScheduleFrequency frequency : frequencyList) {
                //拆分具体上课日期
                List<String> dayList = new ArrayList<>(Arrays.asList(frequency.getDayOfWeek().split(",")));
                for (String day : dayList) {
                    if (!days.contains(Integer.valueOf(day))) {
                        days.add(Integer.valueOf(day));
                    }
                }
            }
            StringBuffer dayStr = new StringBuffer();
            for (Integer day : days) {
                dayStr.append("周" + CommonUtil.NumberToChinese(day.toString()) + "/");
            }
            rows_d.put("project_" + (i + 1), dayStr.toString().substring(0, dayStr.length() - 1));
        }
        //内容
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        list.add(rows_t);
        list.add(rows_c);
        list.add(rows_d);
        for (CoursePublishFrequency csf : coursePublishFrequencyList) {
            Map<String, Object> map = new HashMap<>();
            map.put("column_1", "第" + csf.getFrequencyIndex() + "轮（" + csf.getWeekStart() + "-" + csf.getWeekEnd() + "周）");
            for (int i = 0; i < scheduleVoList.size(); i++) {
                StringBuffer stus = new StringBuffer();
                for (CourseSelectionResultVo csItem : selectionList) {
                    //同一轮次的课
                    if (csItem.getCourseScheduleId().equals(scheduleVoList.get(i).getId()) && csItem.getFrequencyIndex().equals(csf.getFrequencyIndex())) {
                        stus.append(csItem.getStudentName()+"("+csItem.getStudentNum()+")" + "/");
                    }
                }
                if (StringUtils.isNotBlank(stus)) {
                    stus = new StringBuffer(stus.toString().substring(0, stus.length() - 1));
                }
                map.put("project_" + (i + 1), stus.toString());
            }
            list.add(map);
        }
        //文件名称
        String fileName = "课表-" + coursePublishResult.getCollegeName() + "[" + coursePublishResult.getSchoolYearName() + "]" + "[" + coursePublishResult.getTermName() + "]" + "[" + coursePublishResult.getCourseName() + "]";
        PoiUtil.exportExcelWithStream2(fileName + ".xls", beanList, list);
    }

    @Override
    public List<CourseSelectionStuVo> getStuList(CourseSelectionQryDto dto) {
        return courseSelectionMapper.getStuList(dto);
    }

    @Override
    public List<CourseSelectionStuVo> getStuAllList(CourseSelectionQryDto dto) {
        return courseSelectionMapper.getStuAllList(dto);
    }
}
